home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-05
/
pcb121.zip
/
PACKET.INC
< prev
next >
Wrap
Text File
|
1992-01-23
|
12KB
|
373 lines
;;******************************************************************************
;; packet.inc packet.inc
;;******************************************************************************
;;
;; Copyright (C) 1989 Vance Morrison
;;
;;
;; Permission to view, compile, and modify for LOCAL (intra-organization)
;; USE ONLY is hereby granted, provided that this copyright and permission
;; notice appear on all copies. Any other use by permission only.
;;
;; Vance Morrison makes no representations about the suitability
;; of this software for any purpose. It is provided "as is" without expressed
;; or implied warranty. See the copywrite notice file for complete details.
;;
;;******************************************************************************
;; packet.inc contains the interface driver for the the packet driver
;; (a la FTP software, drivers and info available from sun.soe.clarson.edu)
;;
;; Note that this interface driver is VERY inefficient. basically packets
;; are copyied once on read and once again on write. Thus this driver will
;; be at best 1/3 the speed of a native driver. Nevertheless, this speed
;; may be acceptable, (and besides it gets all those people who want 3Com
;; support off my back). There are other inefficiencies as well (saving
;; and restoring registers, waiting for packets to be sent etc), but even
;; so it will be usefull for low performance applications.
;;
;; Note that this these routines do not use any extended or high performance
;; packet driver calls. Only the basic calls are used
;;
;; The functions provided by this file are
;;
;; PKT_DECLARE name, driver_int, driver_class, prom
;; PKT_DEFINE name, fail
;; PKT_IF_R_ACCESS_out_BX_CX_ES name, no_packet
;; PKT_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES name, ok
;; PKT_IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
;; PKT_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP name, no_buffer
;; PKT_IF_W_WRITE_in_CX_const_BX_BP_ES name
;; PKT_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES name
;; PKT_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES name
;;
;; Variables set by this module
;;
;; pkt_&name&_declared ;; one if this interface exists
;; if_&name&_address ;; the hardware address
;; if_&name&_mtu ;; the maximum trans unit
;;
;;******************************************************************************
;;******************************************************************************
;; data storage needed by this module
pkt_r_q_entry STRUC
pkt_q_rstart DW ?
pkt_q_rend DW ?
pkt_r_q_entry ENDS
pkt_data STRUC
pkt_handle DW ?
pkt_bend DW ?
pkt_bstart DW ?
pkt_data ENDS
;;******************************************************************************
;; IF_DECLARE name, driver_int driver_class, promiscuous
;; declares an interface object. driver_int is the interupt number
;; to use to access the packet driver (60H-80H). driver_class is
;; the packet driver class of the card (Ethernet = 1)
;;
PKT_DECLARE MACRO name, driver_int, driver_class, promiscuous
.errb <name>
.errb <driver_int>
.DATA
pkt_&name&_declared = 1
pkt_&name&_drv_int = driver_int
pkt_&name&_drv_class = driver_class
pkt_&name&_rbuff = name*100+1
pkt_&name&_rqueue = name*100+2
pkt_&name&_promiscuous = 0
ifnb <promiscuous>
pkt_&name&_promiscuous = 0&promiscuous
endif
if_&name&_mtu = 1514
global pkt_&name&_wbuffer:byte
global pkt_&name&_rbuffer:byte
global pkt_&name&_data:pkt_data
global if_&name&_address:word
.CODE
global pkt_&name&_data_seg:word
global pkt_&name&_real_define:near
BUFF_DECLARE %pkt_&name&_rbuff, 10240, pkt_&name&_rbuffer
QUEUE_DECLARE %pkt_&name&_rqueue, 16, %(size pkt_r_q_entry)
ENDM
;;******************************************************************************
;; IF_DEFINE name, fail
;; sets asside memory an name object and initializes it. This
;; routine is a no-op if 'name' was not declared. It jumps to 'fail'
;; if there was an error in setup.
;;
PKT_DEFINE MACRO name, fail
ifdef pkt_&name&_declared
BUFF_DEFINE %pkt_&name&_rbuff
QUEUE_DEFINE %pkt_&name&_rqueue
call pkt_&name&_real_define
or AX, AX
jnz fail
endif
ENDM
PKT_REAL_DEFINE MACRO name
local pkt_read_task, got_driver, got_address, size_check, no_room, done
local set_prom
.errb <name>
ifdef pkt_&name&_declared
.DATA
if_&name&_address DW 3 DUP (0)
pkt_&name&_rbuffer DB 10240 dup (0)
pkt_&name&_wbuffer DB 1536 dup (0)
pkt_&name&_data pkt_data <> ;; create storage needed
.CODE
;;*****************************************************************
pkt_&name&_real_define:
mov word ptr cs:pkt_&name&_data_seg, DS
mov AH, 2 ;; access_type driver call
mov AL, pkt_&name&_drv_class ;; driver class
mov DL, 0 ;; wildcard number
mov BX, 0FFFFH ;; wildcard Type
xor CX, CX ;; get any packet type
mov DI, CS ;; point to my packet reciever
mov ES, DI
mov DI, offset pkt_read_task
stc
PKT_CALL_DRIVER name
jnc got_driver
mov DL, DH
xor DH, DH
mov AX, DX
ret
got_driver:
mov pkt_&name&_data.pkt_handle, AX
mov BX, AX
mov AH, 6 ;; get ethernet address
mov DX, DS
mov ES, DX
mov DI, offset if_&name&_address
mov CX, 6 ;; length of address buffer
stc
PKT_CALL_DRIVER name
jnc got_address
mov DL, DH
xor DH, DH
mov AX, DX
ret
got_address:
if pkt_&name&_promiscuous eq 1
mov BX, pkt_&name&_data.pkt_handle
mov AH, 20 ;; set recieve mode
mov CX, 6 ;; to recieve all packets
stc
PKT_CALL_DRIVER name
jnc set_prom
mov DL, DH
xor DH, DH
mov AX, DX
ret
set_prom:
endif
xor AX, AX
sti ;; turn on interupts if they are not already on
ret
;;*********************************************************************
;; 'interupt' routine
pkt_&name&_data_seg: DW 0
pkt_read_task:
push DS
segcs
mov DS, word ptr pkt_&name&_data_seg
or AX, AX
jz size_check
QUEUE_ENQUEUE_out_DI_const_BX_CX_DX_BP_SI_ES %pkt_&name&_rqueue, done
mov AX, pkt_&name&_data.pkt_bstart
mov [DI+pkt_q_rstart], AX
mov AX, pkt_&name&_data.pkt_bend
mov [DI+pkt_q_rend], AX
done:
pop DS
retf
size_check:
BUFF_CHECK_in_CX_out_SI_DI_const_BX_CX_DX_BP_ES %pkt_&name&_rbuff,no_room
BUFF_GET_in_DI_const_AX_BX_CX_DX_BP_SI_DI_ES %pkt_&name&_rbuff
mov pkt_&name&_data.pkt_bstart, SI
mov pkt_&name&_data.pkt_bend, DI
mov DI, SI
mov AX, DS
mov ES, AX
pop DS
retf
no_room:
xor DI, DI
mov ES, DI
pop DS
retf
endif
ENDM
;;******************************************************************************
;; PKT_CLOSE
;; closes the packet driver gracefully
;;
PKT_CLOSE MACRO name
mov AH, 3 ;; CLOSE command
mov BX, pkt_&name&_data.pkt_handle
PKT_CALL_DRIVER name
ENDM
;;******************************************************************************
;; IF_R_ACCESS_out_BX_ES name, no_packet
;; IF_R_ACCESS checks for the next packet to come from the the board
;; associated with 'name' and returns a pointer to the begining of
;; an ethernet packet in BX:ES. CX holds the length of the packet
;; R_ACCESS jumps to 'no_packet' if there are no packets waiting to
;; be read in
;;
PKT_IF_R_ACCESS_out_BX_CX_ES MACRO name, no_packet
.errb <no_packet>
QUEUE_HEAD_out_SI_const_AX_BX_CX_DX_BP_DI_ES %pkt_&name&_rqueue, no_packet
mov BX, [SI+pkt_q_rstart]
mov CX, [SI+pkt_q_rend]
sub CX, BX
mov AX, DS
mov ES, AX
ENDM
;;******************************************************************************
;; IF_R_FREE_const_BX_CX_BP_SI_DI_ES name
;; After the client is through processing the packet returned by
;; IF_R_ACCESS, IF_R_FREE must be called to inform 'name' that the
;; memory that the packet was in can be reused for future packets.
;;
PKT_IF_R_FREE_const_BX_CX_BP_SI_DI_ES MACRO name
local done
.errb <name>
cli
QUEUE_HEAD_out_SI_const_AX_BX_CX_DX_BP_DI_ES %pkt_&name&_rqueue, done
mov DI, [SI+pkt_q_rend]
BUFF_FREE_in_DI_const_AX_BX_CX_DX_BP_SI_DI_ES %pkt_&name&_rbuff
QUEUE_DEQUEUE_in_SI_const_AX_BX_CX_DX_BP_DI_ES %pkt_&name&_rqueue
done:
sti
ENDM
;;******************************************************************************
;; PKT_IF_R_CONT_in_BX_CX_ES name, ok
;; IF_R_CONT determines if the packet returned by R_READ in BX:ES
;; of length CX is continuous. If it is it jumps to 'ok' otherwise
;; it just returns
;;
PKT_IF_R_CONT_in_BX_CX_ES_const_BX_CX_DX_BP_SI_DI_ES MACRO name, ok
.errb <ok>
jmp ok ;; is it always continuous
ENDM
;;******************************************************************************
;; IF_W_ACCESS_in_CX_out_DI_ES name, no_buffer
;; IF_W_ACCESS returns a pointer to an output buffer for a packet. The
;; pointer is returned in DI:ES. If the ouptut buffer is busy, this
;; routine will jump to 'no_buffer'. The output buffer min(CX, 1536)
;; bytes long
;;
PKT_IF_W_ACCESS_in_CX_out_DI_ES_const_BX_CX_BP MACRO name, no_buffer
.errb <no_buffer>
mov DI, offset pkt_&name&_wbuffer
mov AX, DS
mov ES, AX
ENDM
;;******************************************************************************
;; IF_W_WRITE_in_CX name
;; IF_W_WRITE actually signals the ethernet board to write a packet to
;; the ethernet. The packet is assumed to be in the buffer returned by
;; IF_W_ACCESS. CX is the length of the packet to send.
;;
PKT_IF_W_WRITE_in_CX_const_BX_BP_ES MACRO name
.errb <name>
push BX
push BP
push ES
mov AH, 4 ;; set_pkt command
mov SI, offset pkt_&name&_wbuffer ;; the packet to send
;; DS is OK as it stands
;; CX is also fine as is
PKT_CALL_DRIVER name
pop ES
pop BP
pop BX
ENDM
;;******************************************************************************
;; IF_SET_ADDRESS_in_SI name
;; IF_SET_ADDRESS_in_SI sets the hardware address to be the value
;; pointed to by SI. Note this function may be a no-op if the
;; hardware address cannot be set (ETHERNET for example)
;;
PKT_IF_SET_ADDRESS_in_SI_const_BX_CX_BP_DI_ES MACRO name
.err ;; we don't support setting ethernet addresses (yet)
ENDM
;;******************************************************************************
;; IF_COPY_in_CX_SI_DI_ES_out_SI_DI name
;; IF_COPY_in_CX_SI_DI_ES copys a packet from the input buffer (pointed
;; to by SI and the segement register given in IF_DECLARE) to an output
;; buffer (pointed to by DI and ES) of length CX. It assumes the
;; output buffer is contiguous. (and the caller shouln't care if the
;; input buffer is contiguous)
;;
PKT_IF_COPY_in_CX_SI_DI_ES_out_SI_DI_const_BX_BP_ES MACRO name
.errb <name>
;; since DS points to the data segment, we are ready to go!!
inc CX
shr CX,1
rep movsw
ENDM
;;******************************************************************************
;; PKT_CALL_DRIVER calls the drivers, but it also makes sure that the
;; segment registers are preserved.
PKT_CALL_DRIVER MACRO name
.errb <name>
push DS
push SS
int pkt_&name&_drv_int
pop SS
pop DS
ENDM